﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.Diagnostics;
using BulldogCMS.Core.Storage.DataTypes;

namespace BulldogCMS.Core.Templates
{
    [DebuggerDisplay("{Name}")]
    public class TemplateMeta
    {
        private List<FieldMeta> _fieldMetasWithInherited = null;
        private List<FieldGroupMeta> _fieldGroupsMetas = null;
        private List<string> _baseTemplates = null;

        public string Name
        {
            get;
            private set;
        }

        public IEnumerable<FieldMeta> FieldMetas {
            get {
                foreach (var groupMeta in _fieldGroupsMetas)
                {
                    foreach (var field in groupMeta.FieldMetas)
                    {
                        yield return field;
                    }
                }
            }
        }

        public IEnumerable<FieldMeta> FieldMetasWithInherited {
            get {
                List<FieldMeta> fieldMetas = new List<FieldMeta>();
                fieldMetas.AddRange(this.FieldMetas);
                foreach (var baseTemplatePath in this._baseTemplates)
                {
                    string templateName = baseTemplatePath.Replace("assembly://", string.Empty);
                    TemplateMeta templateMeta = Context.Application.Templates.Where(p => p.Name == templateName).FirstOrDefault();
                    if (templateMeta != null)
                    {
                        foreach (var fieldMeta in templateMeta.FieldMetasWithInherited)
                        {
                            if (!fieldMetas.Any(p=>p.Name == fieldMeta.Name)) {
                                fieldMetas.Add(fieldMeta);
                            }
                        }
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Template {0} not found", templateName));
                    }
                }

                return fieldMetas;
            }
        }

        public bool IsFieldShared(string fieldName)
        {
            return this.FieldMetasWithInherited.Any(p => p.Name == fieldName && p.IsShared);
        }

        public TemplateMeta()
        {

        }

        internal TemplateMeta(string templateName, XDocument templateDoc)
        {
            this.Name = templateName;
            this._fieldGroupsMetas = this.LoadFieldGroups(templateDoc);
            this._baseTemplates = this.LoadBaseTemplates(templateDoc);
        }

        private List<FieldGroupMeta> LoadFieldGroups(XDocument templateDoc)
        {
            List<FieldGroupMeta> fieldGroupMetas = new List<FieldGroupMeta>();
            XElement fieldGroupMetasEl = templateDoc.Root.Element("fieldGroups");
            if (fieldGroupMetasEl != null)
            {
                foreach (XElement fieldGroupMetaEl in fieldGroupMetasEl.Elements())
                {
                    fieldGroupMetas.Add(new FieldGroupMeta(fieldGroupMetaEl));
                }
            }
            return fieldGroupMetas;
        }

        private List<string> LoadBaseTemplates(XDocument templateDoc)
        {
            List<string> baseTemplates = new List<string>();
            XElement baseTemplatesEl = templateDoc.Root.Element("baseTemplates");
            if (baseTemplatesEl != null)
            {
                foreach (XElement templateLink in baseTemplatesEl.Elements())
                {
                    string templateUrl = templateLink.GetAttributeValue<string>("path");
                    baseTemplates.Add(templateUrl);
                }
            }
            return baseTemplates;
        }

        public bool ValidateField(string fieldName, Type type = null)
        {
            FieldMeta fieldMeta = this.FieldMetasWithInherited.Where(p => p.Name == fieldName).FirstOrDefault();
            if (fieldMeta != null)
            {
                if (type != null)
                {
                    if (type != typeof(BulldogCMS.Core.Storage.DataTypes.BaseDataType))
                    {
                        if (fieldMeta.Type == type.FullName)
                        {
                            return true;
                        }
                        return false;
                    }
                }
                return true;
            }
            return false;
        }

    }

    [DebuggerDisplay("{Name} - {Type}")]
    public class FieldMeta
    {
        public string Name
        {
            get;
            internal set;
        }

        public string DisplayName
        {
            get;
            internal set;
        }

        public string Type
        {
            get;
            internal set;
        }

        public bool IsShared
        {
            get;
            internal set;
        }

    }

    public class FieldGroupMeta
    {
        private List<FieldMeta> _fieldMetas = new List<FieldMeta>();

        public IEnumerable<FieldMeta> FieldMetas
        {
            get
            {
                return this._fieldMetas;
            }
        }

        public FieldGroupMeta(XElement fieldGroupMetaEl)
        {
            this.Title = fieldGroupMetaEl.GetAttributeValue<string>("title");
            foreach (XElement fieldMetaEl in fieldGroupMetaEl.Elements())
            {
                FieldMeta fieldMeta = new FieldMeta()
                {
                    Name =          fieldMetaEl.GetAttributeValue<string>("name"),
                    DisplayName =   fieldMetaEl.GetAttributeValue<string>("displayName"),
                    Type =          fieldMetaEl.GetAttributeValue<string>("type"),

                };
                this._fieldMetas.Add(fieldMeta);
            }
        }

        public string Title
        {
            get;
            set;
        }


    }

}
